home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir41 / wcpu050.zip / WCPU.ASM next >
Assembly Source File  |  1993-03-12  |  18KB  |  411 lines

  1. ; TASM 2.0 required
  2. quirks
  3. masm51
  4.  
  5. code    SEGMENT  WORD PUBLIC 'CODE'
  6.  
  7.         ASSUME  CS:code
  8.         public GetProz,CoPro,DXorSX
  9.  
  10. ;**********************************************************************;
  11. ;*                             P R O Z P A                            *;
  12. ;*--------------------------------------------------------------------*;
  13. ;*    Aufgabe        : Ermittelt den Typ von Prozessor, der in einem  *;
  14. ;*                     PC installiert ist.                            *;
  15. ;*                     In dieser Version ist das Programm zur Um-     *;
  16. ;*                     wandlung in INLINE-Befehle und damit zur Ein-  *;
  17. ;*                     bindung in ein PASCAL-Programm vorgesehen.     *;
  18. ;*--------------------------------------------------------------------*;
  19. ;*    Autor          : MICHAEL TISCHER                                *;
  20. ;*    entwickelt am  : 22.08.1988                                     *;
  21. ;*    letztes Update : 22.08.1988                                     *;
  22. ;*                                                                    *;
  23. ;*    Modifiziert von Michael Holin (486,Pentium-Erkennung)           *;
  24. ;*                                                                    *;
  25. ;**********************************************************************;
  26.                                                                         
  27. ;== Konstanten =========================================================
  28. p_pentium equ   9
  29. p_80486   equ   8
  30. p_80386   equ   7
  31. p_80386sx equ   7                 ;Codes für die verschiedenen Pro-
  32. p_80286   equ   6                 ;zessortypen
  33. p_80186   equ   5
  34. p_80188   equ   4
  35. p_v30     equ   3
  36. p_v20     equ   2
  37. p_8086    equ   1
  38. p_8088    equ   0
  39.  
  40. ;fernen haben die Bits 5-7 folgende Bedeutung:
  41. ;
  42. ;                                    8 7 6 5 | 4 3 2 1
  43. ;   Weitek-Coprozessor vorhanden ──────┘ │ │
  44. ;   Coprozessor wird emuliert ───────────┘ │
  45. ;   CPU ist im Virtual Mode ───────────────┘
  46.  
  47. ;== Code ===============================================================
  48.  
  49.                                                                         
  50. getproz   proc far               ;diese Prozedur ist das eigentliche
  51.                                   ;Hauptprogramm
  52.           push bp
  53.       mov bp,sp                                                              
  54.           pushf                   ;den Inhalt des Flag-Registers sichern
  55.           push cx                 ;den Inhalt aller veränderten Register
  56.           push dx                 ;auf dem Stack sichern
  57.           push di
  58.           push si
  59.           push es
  60.           ;-- auf 80386/80286 testen -----------------------------------
  61.                                                                         
  62.           xor  ax,ax              ;AX auf 0 setzen
  63.           push ax                 ;und auf den Stack bringen
  64.           popf                    ;als Flag-Register vom Stack holen
  65.           pushf                   ;wieder auf den Stack bringen
  66.           pop  ax                 ;und als AX zurückholen
  67.           and  ax,0f000h          ;nur die oberen 4 Bits nicht löschen
  68.           cmp  ax,0f000h          ;sind die Bits 12 - 15 alle gleich 1?
  69.           je   nicht_386          ;JA, kann kein 80386 oder 80286 sein
  70.                                                                         
  71.           ;-- testen, ob es sich um 80386 oder 80286 handelt -----------
  72.                                                                         
  73.           mov  dl,p_80286         ;es handelt sich auf jeden Fall um
  74.           mov  ax,07000h          ;einen der Beiden Prozessoren
  75.           push ax                 ;den Wert 07000h auf den Stack bringen
  76.           popf                    ;als Flag-Register zurückholen
  77.           pushf                   ;und wieder auf den Stack bringen
  78.           pop  ax                 ;in das AX-Register zurückholen
  79.           and  ax,07000h          ;nur die Bits 12 - 14 nicht ausblenden
  80.           je   pende              ;sind die Bits 12 - 14 alle gleich 0?
  81.                                   ;JA --> es handelt sich um einen 80286
  82.                                                                         
  83.           inc  dl                 ;Nein, es handelt sich um einen 80386
  84.                                   ;oder 80486
  85. .386p
  86.           call is486              ;Test auf 486 und Pentium
  87.           smsw bx
  88.           test bl,4               ;Koprozessor-Emulation ?
  89.           jz   short @f
  90.           or   dl,32              ;JA, dann 32 draufaddieren
  91. @@:       test bl,1               ;CPU in Virtual Mode ?
  92.           jz  short @f
  93.           or  dl,16               ;JA, dann 16 draufaddieren
  94. @@:       xor  eax,eax
  95.           int  11h                ;Weitek-Prozessor installiert?
  96.           test eax,1000000h
  97.           jz  pende
  98.           or  dl,64               ;dann 64 draufaddieren
  99. ;          jmp pende
  100.  
  101.  
  102.                            
  103. pende:              ;die Testes sind abgeschlossen
  104.  
  105.           xor ax,ax
  106.           mov  al,dl              ;Proz.Code in Return-Var. ablegen
  107.           pop  es                 ;die gesicherten Register wieder vom
  108.           pop  si                 ;Stack holen
  109.           pop  di
  110.           pop  dx
  111.           pop  cx
  112.           popf                    ;Flag-Register wieder vom Stack holen
  113.           jmp  ende               ;zurück zum Aufrufer
  114.           ;-- auf 80186 bzw. 80188 testen ------------------------------
  115.                                                                         
  116. nicht_386:
  117.                                                                         
  118.           mov  dl,p_80188         ;Code für 80188 laden
  119.           mov  al,0ffh            ;alle Bits im AL-Register auf 1 setzen
  120.           mov  cl,021h            ;Anzahl der Shift-Operationen nach CL
  121.           shr  al,cl              ;AL CL mal nach rechts verschieben
  122.           jne  short t88_86       ;AL ist nicht 0, es muß sich um den
  123.                                   ;80188 oder 80186 handeln
  124.                                                                         
  125.           ;-- auf NEC V20 oder V30 testen ------------------------------
  126.                                                                         
  127.           mov  dl,p_v20           ;Code für NEC V20 laden
  128.           sti                     ;Interrupts sollen erlaubt sein
  129.           mov  si,0               ;mit dem ersten Byte in ES beginnen
  130.           mov  cx,0ffffh          ;ein komplettes Segment lesen
  131.           rep  lods byte ptr es:[si]      ;REP mit einem Segment-Override
  132.                                   ;funktioniert nur bei NEC V20, V30
  133.           or   cx,cx              ;wurde das komplette Segment gelesen?
  134.           je   t88_86             ;JA --> ist V20 oder V30
  135.                                                                         
  136.           mov  dl,p_8088          ;NEIN --> muß 8088 oder 8086 sein
  137.                                                                         
  138.           ;-- auf ...88 oder ...86 bzw. V20 oder V30 testen ------------
  139.                                                                         
  140. t88_86:
  141.                                                                         
  142.           push cs                 ;CS auf dem Stack merken
  143.           pop  es                 ;und als ES zurückholen
  144.           std                     ;bei Stringbefehlen abwärts zählen
  145.           mov  al,0fbh            ;Befehlscode für "STI"
  146.           mov  cx,3               ;den Stringbefehl 3 mal ausführen
  147.           call get_di             ;Startadresse DI holen
  148. t86_1:    cli                     ;Interrupts unterdrücken
  149.           rep  stosb
  150.           cld                     ;bei Stringbefehlen wieder aufwärts
  151.           nop                     ;Dummy-Befehle zum Queue füllen
  152.           nop
  153.           nop
  154.                                                                         
  155.           inc  dx                 ;Prozessorcode inkrementieren
  156.           nop
  157. q_end:    sti                     ;Interrupts wieder erlauben
  158.           jmp pende
  159.                                                                        
  160.           ;-------------------------------------------------------------
  161.  
  162.                                                                         
  163. getproz   endp                    ;Ende der PROG-Prozedur
  164.  
  165. is486 proc    ;-- Der folgende Test zwischen 80386 und 80486 beruht auf ----
  166.           ;-- einer Erweiterung des EFlags-Registers beim 80486 in
  167.           ;-- Bitposition 18.
  168.           ;-- Dieses Flag gibt es beim 80386 nicht, und deshalb läßt
  169.           ;-- sich sein Inhalt auch nicht per Software verändern.
  170.  
  171.           cli                  ;keine Interrupts jetzt
  172.  
  173.           mov    ebx,esp       ;aktuelles SP merken
  174.           and    esp,0FFFCh    ;auf DWORD abrunden
  175.           pushfd               ;Flag-Register über
  176.           pop    eax           ;Stack nach AX
  177.           mov    ecx,eax       ;und in CX merken
  178.           xor    eax,1 shl 18  ;Alignment-Bit umdrehen
  179.           push   eax           ;und in das Flag-
  180.           popfd                ;Register bringen
  181.           pushfd               ;Flag wieder auf Stack
  182.           pop    eax           ;und dann nach AX
  183.           push   ecx           ;alten Flag-Inhalt
  184.           popfd                ;wieder zurück
  185.           xor    eax,ecx       ;AL-Bit testen
  186.           shr    eax,18        ;AL-Bit nach Bit 0
  187.           and    eax,1h        ;alle anderen ausbl.
  188.           mov    esp,ebx       ;SP wieder zurücks.
  189.  
  190.           add  dl,al              ;AL ist 1, wenn 486
  191.  
  192.  
  193.           mov    ebx,esp       ;aktuelles SP merken
  194.           and    esp,0FFFCh    ;auf DWORD abrunden
  195.           pushfd               ;Flag-Register über
  196.           pop    eax           ;Stack nach AX
  197.           mov    ecx,eax       ;und in CX merken
  198.           xor    eax,1 shl 21  ;ID-Bit umdrehen
  199.           push   eax           ;und in das Flag-
  200.           popfd                ;Register bringen
  201.           pushfd               ;Flag wieder auf Stack
  202.           pop    eax           ;und dann nach AX
  203.           push   ecx           ;alten Flag-Inhalt
  204.           popfd                ;wieder zurück
  205.           xor    eax,ecx       ;AL-Bit testen
  206.           shr    eax,21        ;AL-Bit nach Bit 0
  207.           and    eax,1h        ;alle anderen ausbl.
  208.           mov    esp,ebx       ;SP wieder zurücks.
  209.  
  210.           sti                     ;Interrupts wieder erlauben
  211.           add  dl,al              ;AL ist 1, wenn Pentium
  212.           ret
  213. is486 endp
  214.                                                                         
  215. ;-- GET_DI ermittelt DI für 88/86-Test ---------------------------------
  216.                                                                         
  217. get_di:
  218.                                                                         
  219.           pop  di                 ;Rücksprungadresse vom Stack holen
  220.           add  di,9               ;9 Bytes davon entfernt anfangen
  221.           jmp  t86_1              ;wieder in die Testroutine springen
  222.                                                                         
  223. ende:
  224.           mov sp,bp
  225.       pop bp
  226.           ret                                                                        
  227.  
  228.  
  229. .8086
  230.  
  231. ;== Ende ===============================================================
  232.  
  233.  
  234. .386
  235. DXorSX  proc far                    ;Mem-Access via DWord-Read
  236.         assume  cs:CODE, es:nothing
  237.         push bp
  238.         mov bp,sp
  239.         push ds
  240.         push es
  241.         push si
  242.         push di
  243.         push cx
  244.         pushf
  245.         mov ax,0040h
  246.         mov ds,ax
  247.         mov bx,00F0h
  248.         xor ecx,ecx
  249.         xor esi,esi
  250.         mov cx,word ptr ds:bx           ;Anzahl
  251.         mov si,word ptr ds:bx + 2       ;Offset
  252.         mov ax,word ptr ds:bx + 4       ;Segment
  253.         mov ds,ax
  254.         cld
  255.         cli
  256.         mov al,34h
  257.         out 43h,al
  258.         jmp $+2
  259.         mov al,0
  260.         out 40h,al
  261.         jmp $+2
  262.         out 40h,al
  263.         rep
  264.         lodsd
  265.  
  266.         mov al,0
  267.         out 43h,al
  268.         sti
  269.         jmp $+2
  270.         in al,40h
  271.         xchg ah,al
  272.         jmp $+2
  273.         in al,40h
  274.         xchg ah,al
  275.         neg ax             ;return time for doing the loop
  276.         popf
  277.         pop cx
  278.         pop di
  279.         pop si
  280.         pop es
  281.         pop ds
  282.         mov sp,bp
  283.         pop bp
  284.         ret
  285. DXorSX endp
  286.  
  287.  
  288. .8086
  289. ;   calling convention:
  290. ;
  291. ;    function CoPro:word;
  292. ;
  293. ;   returns:
  294. ;
  295. ;       tucked away neatly in your AX....
  296. ;
  297. ;                     0 if NO NDP is found
  298. ;                     1 if an 8087
  299. ;                     2 if an 80287
  300. ;                     3 if an 80387
  301. ;
  302. ;   NOTE:
  303. ;
  304. ;       There are lotsa ways of handling the way this function returns
  305. ;       it's data.  For my purposes, I have elected this one because
  306. ;       it requires only int arithmetic on the caller's end to extract
  307. ;       all the info I need from the return value.  I think that I'm
  308. ;       well enough 'commented' in the following code so that you will
  309. ;       be able to tinker and Putz until you find the best return tech-
  310. ;       nique for Ur purposes without having to reinvent the wheel.
  311. ;
  312. ;   REFERENCES:
  313. ;
  314. ;       ndp_type is adopted from Ted Forgeron's article in PC
  315. ;         Tech Journal, Aug '87 p43.
  316. ;
  317. ;     In the event of subsequent republication of this function,
  318. ;       please carry forward reference to these two gentlemen as
  319. ;       original authors.
  320. ;
  321. ;       Copr. 1987      Pat Shea - Psi! (that Copr. is on there cuz my
  322. ;                                        lawyer sez I should, but feel
  323. ;                                        free to hack away!!!    pats.)
  324. ;
  325. ;       Update:   1/1/88 - changed this code slightly so that it is
  326. ;                          compilable using MASM 5.0, and the test.c
  327. ;                          file using MSC 5.0. <Albert Stein>
  328. ;
  329.  
  330. CoPro   proc far
  331.         assume  cs:CODE, es:nothing
  332.         push   BP             ; save where Ur at
  333.         mov    BP,SP          ;   going in.....
  334.  
  335.         push   DI
  336.         push   SI
  337.         push   CX             ; not really needed for MSC but kinda
  338.                               ;   nice to do cuz someone else might
  339.                               ;   want to use the function and we do
  340.                               ;   use CX later on
  341.  
  342.         call   ndp_type       ; check for math coprocessor (NDP) type
  343.                               ;   and hold that result in AX
  344.  
  345.         pop    CX             ; put things back the way that you
  346.         pop    SI             ;   found 'em when you started this
  347.         pop    DI             ;   little drill off.....
  348.         pop    BP
  349.                               ; AND
  350.         ret                   ; go back to where you came from....
  351.                               ;   ( ===>  the calling program )
  352.                               ;   with Ur results sittin' in AX !!
  353.         even
  354. control dw     0              ; control word needed for the NDP test
  355.  
  356. CoPro         endp
  357.  
  358.  
  359. ; Check for an NDP.
  360. ;
  361.  
  362. ndp_type       PROC
  363.  
  364. do_we:  fninit                          ; try to initialize the NDP
  365.         mov    byte ptr control+1,0     ; clear memory byte
  366.         fnstcw control                  ; put control word in memory
  367.         mov    AH,byte ptr control+1    ; iff AH is 03h, you got
  368.         cmp    AH,03h                   ;   an NDP on board !!
  369.         je     chk_87                   ; found somethin', keep goin'
  370.         xor    AX,AX                    ; clean out AX to show a zero
  371.         jmp    SHORT NDPbye             ;   return (i.e., no NDP)
  372.  
  373. ; 'got an 8087 ??
  374.  
  375. chk_87: and    control,NOT 0080h        ; turn ON interrupts (IEM = 0)
  376.         fldcw  control                  ; load control word
  377.         fdisi                           ; turn OFF interrupts (IEM = 1)
  378.         fstcw  control                  ; store control word
  379.         test   control,0080h            ; iff IEM=1, 8087
  380.         jz     chk287                   ; 'guess not!  March on....
  381.         mov    Ax,1                     ; set up for a 1 return to
  382.         jmp    SHORT NDPbye             ;   show an 8087 is on board
  383. ; if not.... would you believe an 80287 maybe ??
  384. .286
  385. CHK287: finit                 ; set default infinity mode
  386.         fld1                  ; make infinity
  387.         fldz                  ;   by dividing
  388.         fdiv                  ;   1 by zero !!
  389.         fld    st             ; now make a
  390.         fchs                  ;   negative infinity
  391.         fcompp                ; compare Ur two infinities
  392.         fstsw  control        ; iff, for 8087 or 80287
  393.         fwait                 ; sit tight 'til status word is put away
  394.         mov    AX,control     ; getchur control word
  395.         sahf                  ; putchur AH into flags
  396.         jnz    got387         ; NO GOOD.... march on !!
  397.         mov    Ax,2           ; gotta be a 80287 cuz we already tested
  398.         jmp    SHORT NDPbye   ;   for an 8087
  399.  
  400. ; We KNOW that there is an NDP on board otherwise we would have bailed
  401. ; out after 'do_we'.  It isn't an 8087 or an 80287 or we wouldn't have
  402. ; gotten this far.  It's gotta be an 80387 !!
  403. got387: mov    ax,3           ; call it an 80387 and return 3
  404. NDPbye: ret                   ; and go back where you came from
  405.                               ;   (i.e., ===>  _chips) carrying the NDP
  406.                               ;   type in Ur DL register
  407. ndp_type       endp
  408.  
  409. code ends
  410. end
  411.